// *************************************
// * Creator:SunnyPaine
// * DateTime:2024/08/14 16:08:32
// * Description:<Description>
// * CopyRight:
// * ***********************************

using System;
using System.Windows;
using System.Windows.Data;
using System.Windows.Interactivity;
using System.Windows.Navigation;

namespace SunnyPaine.Autofac.Extension.Mvvm.UI
{
    /// <summary>
    /// 提供Behavior的基础服务。
    /// </summary>
    public abstract class BaseService : Behavior<FrameworkElement>
    {
        /// <summary>
        /// Behavior基础服务的帮助类。
        /// </summary>
        internal static class BaseServiceHelper
        {
            public static void SetBinding(BaseService service)
            {
                BindingOperations.SetBinding(service, BaseService.ServiceClientInternalProperty,
                    new Binding()
                    {
                        Path = new PropertyPath("DataContext"),
                        Source = service.AssociatedObject
                    });
            }

            public static void ClearBinding(BaseService service)
            {
                BindingOperations.ClearBinding(service, BaseService.ServiceClientInternalProperty);
            }

            public static bool IsBindingSet(BaseService service)
            {
                return BindingOperations.IsDataBound(service, BaseService.ServiceClientInternalProperty);
            }
        }


        private bool isLoaded;

        /// <summary>
        /// Behavior的名称。
        /// </summary>
        public static readonly DependencyProperty NameProperty = DependencyProperty.Register("Name", typeof(string), typeof(BaseService), new PropertyMetadata(null));
        private static readonly DependencyProperty ServiceClientInternalProperty = DependencyProperty.Register("ServiceClientInternal", typeof(object), typeof(BaseService), new PropertyMetadata(null, delegate(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((BaseService)d).OnServicesClientChanged(e.OldValue as ISupportUIServices, e.NewValue as ISupportUIServices); }));


        /// <summary>
        /// Behavior的名称。
        /// </summary>
        public string Name
        {
            get { return (string)this.GetValue(NameProperty); }
            set { this.SetValue(NameProperty, value); }
        }

        /// <summary>
        /// 当附加时。
        /// </summary>
        protected override void OnAttached()
        {
            base.OnAttached();
            BaseServiceHelper.SetBinding(this);
        }

        /// <summary>
        /// 当拆卸时。
        /// </summary>
        protected override void OnDetaching()
        {
            BaseServiceHelper.ClearBinding(this);
            base.OnDetaching();
        }

        /// <summary>
        /// 获取UI主线程相关的服务支持。
        /// </summary>
        /// <returns></returns>
        protected ISupportUIServices GetServicesClient()
        {
            return this.GetValue(ServiceClientInternalProperty) as ISupportUIServices;
        }

        /// <summary>
        /// 获取Behavior的基地址。
        /// </summary>
        /// <returns></returns>
        protected Uri GetBaseUri()
        {
            Uri baseUri = BaseUriHelper.GetBaseUri(this);
            if (baseUri != null || base.AssociatedObject == null)
            {
                return baseUri;
            }
            return BaseUriHelper.GetBaseUri(base.AssociatedObject);
        }

        /// <summary>
        /// 当UI主线程相关的服务支持变化时发生。
        /// </summary>
        /// <param name="oldServiceClient"></param>
        /// <param name="newServiceClient"></param>
        protected virtual void OnServicesClientChanged(ISupportUIServices oldServiceClient, ISupportUIServices newServiceClient)
        {
            oldServiceClient?.Container.UnRegister(this, this.Name);
            newServiceClient?.Container.Register(this, this.Name);
        }

        private void OnLoaded(object sender, RoutedEventArgs e)
        {
            if (!this.isLoaded)
            {
                this.isLoaded = true;
                if (!BaseServiceHelper.IsBindingSet(this))
                {
                    BaseServiceHelper.SetBinding(this);
                }
            }
        }

        private void OnUnloaded(object sender, RoutedEventArgs e)
        {
            if (this.isLoaded)
            {
                this.isLoaded = false;
                BaseServiceHelper.ClearBinding(this);
            }
        }

        private void Subscribe()
        {
            if (base.AssociatedObject != null)
            {
                base.AssociatedObject.Loaded += this.OnLoaded;
                base.AssociatedObject.Unloaded += this.OnUnloaded;
            }
        }

        private void Unsubscribe()
        {
            if (base.AssociatedObject != null)
            {
                base.AssociatedObject.Loaded -= this.OnLoaded;
                base.AssociatedObject.Unloaded -= this.OnUnloaded;
            }
        }
    }
}